home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************
- *
- * NOTIMTAB.C
- *
- **************************************************************/
-
- #include <acs.h> /* because of NULL, Ax_malloc(), ... */
- #include <string.h> /* because of memcmp(), ... */
-
- #include <servimem.pif>
- #include <notimtab.pif>
-
-
- /********************************************************************
- */
- int delta(
- NOTE_TIME_TABLE_ELEMENT *border, /* search till border is reached */
- NOTE_TIME_TABLE_ELEMENT *position /* search from position onwards */
- )
- /* Assumes "border" and "position" to be pointers
- * into a note_time_table. "delta" searches - starting from "position"
- * in direction to "border" - for the first note in the table which ma-
- * tches to the one "position" is pointing to. Two notes match - in
- * the sense used here - if note number, channel and source chunk are
- * equal and if the reference of the found note is still initialized.
- *
- * RETURN: d: = 0 , if no match was found or if position == border.
- * = matching position - position , else.
- *
- ********************************************************************/
- {
- int d = 0;
- register NOTE_TIME_TABLE_ELEMENT *current ;
-
- current = position ;
- if (border > position)
- {
- while ( (current < border) && !d )
- {
- current += 1 ;
- if (!current->reference &&
- (current->note == position->note) &&
- (current->channel == position->channel) )
- d = current - position ;
- }
- }
- else if (border < position)
- {
- while ( (current > border) && !d )
- {
- current -= 1 ;
- if (!current->reference &&
- (current->note == position->note) &&
- (current->channel == position->channel) )
- d = current - position ;
- }
- }
- return(d) ;
- }
-
-
-
- /******************************************************************/
- /*********** PUBLISHED INTERFACE (PIF) **************************/
- /******************************************************************/
-
- unsigned int fill_note_time_table
- (
- unsigned char *track_address,
- long track_length,
- NOTE_TIME_TABLE_ELEMENT *first_element,
- long *elements_generated,
- unsigned int *channels,
- NOTE *min_note, NOTE *max_note,
- char *trackname,
- int max_text_length
- )
- {
- event *next_data = track_address, status = 0 ;
- NOTE_TIME_TABLE_ELEMENT *current_element = first_element;
- unsigned long length = 0 ; /* length of sysex or meta events */
- TIME time = 0, delta_time = 0 ;
- unsigned char read_bytes = 0 ;
- int d = 0, /* reference(note on) = - reference(note off) = d */
- EOT_reached = FALSE ;
-
- *channels = 0 ; /* up to now, all are empty */
- *min_note = 0x7f ; *max_note = 0x00 ;
-
- /*** while not end of track reached ***/
- while (!EOT_reached)
- {
- /*** get next time value ***/
- if ( read_var_len(next_data, &delta_time, &read_bytes) )
- return no_var_length_number ;
- next_data += read_bytes ;
- time += delta_time ;
-
- /*** get next event out of this chunk ***/
- if ( (*next_data & MSN) == SYS_EX )
- {
- /*** sysex or meta event or error ***/
- status = 0 ;
- switch (*next_data)
- {
- case SYS_EX: /*** sysex event transmit "f0": ignore ***/
- if ( read_var_len(next_data + 1, &length, &read_bytes)
- == no_var_length_number ) return no_var_length_number ;
- next_data += (1 + read_bytes + length) ; break ;
- case SYS_EX_NT: /*** sysex event not transmit "f0": ignore ***/
- if ( read_var_len(next_data + 1, &length, &read_bytes)
- == no_var_length_number ) return no_var_length_number ;
- next_data += (1 + read_bytes + length) ; break ;
- case META_EVENT: /*** meta event ***/
- next_data += 1 ; /* point to type of meta event */
- if ( read_var_len(next_data + 1, &length, &read_bytes)
- == no_var_length_number ) return no_var_length_number ;
- switch (*next_data)
- {
- case END_OF_TRACK: EOT_reached = TRUE ; break ;
- case SQ_TRCK_NAME:
- if (length >= max_text_length) {
- memcpy(trackname, next_data + 1 + read_bytes, max_text_length - 1) ;
- trackname[max_text_length - 1] = 0 ;
- }
- else {
- memcpy(trackname, next_data + 1 + read_bytes, length) ;
- trackname[length] = 0 ;
- }
- }
- next_data += (1 + read_bytes + length) ;
- break ;
- default:
- return wrong_event_found ;
- }
- }
- else
- {
- /*** midi data or channel message status byte ***/
- if ( !(*next_data & STATUS) )
- {
- /*** data, running status must be given ***/
- if (!status) return data_without_status_given ;
- }
- else
- {
- /*** channel message status byte ***/
- status = *next_data ;
- next_data += 1 ;
- }
- switch (status & MSN)
- {
- case NOTE_OFF: /* for delta: | _ON_ */
- current_element->note = *next_data | _ON_ ;
- current_element->channel = status & LSN ;
- next_data += 1 ;
- current_element->dynamic = *next_data ;
- next_data += 1 ;
- current_element->time = time ;
-
- /*** link note on and note off ***/
- d = delta(first_element, current_element) ;
-
- /*** reset: note off ***/
- current_element->note &= ~_ON_ ;
- current_element->reference = d ;
- (current_element + d)->reference = - d ;
- current_element += 1 ;
- break ;
- case NOTE_ON:
- if (*next_data > *max_note) *max_note = *next_data ;
- if (*next_data < *min_note) *min_note = *next_data ;
- current_element->note = *next_data | _ON_ ;
- current_element->channel = status & LSN ;
- *channels |= 0x1<<(current_element->channel) ;
- next_data += 1 ;
- current_element->dynamic = *next_data ;
- next_data += 1 ;
- current_element->time = time ;
-
- /*** note on with dynamic == 0 is note off ***/
- if (!current_element->dynamic)
- {
- /*** link note on and note off ***/
- d = delta(first_element, current_element) ;
-
- /*** switch note to off ! ***/
- current_element->note &= ~_ON_ ;
- current_element->reference = d ;
- (current_element + d)->reference = - d ;
- current_element += 1 ;
- }
- else
- {
- /*** normal note on: ***/
- /*** initialize reference and continue ***/
- current_element->reference = 0 ;
- current_element += 1 ;
- }
- break ;
- case POLY_KEY_PRESS:
- case CONTROL_CHANGE:
- case PITCH_BEND:
- next_data += 2 ; break ;
- case PROGRAM_CHANGE:
- case CHANNEL_PRESS:
- next_data += 1 ; break ;
- }
- }
- if (next_data - track_address > track_length)
- return next_data_overflow ;
- }
- /*** <-- end while (!EOT_reached) ***/
- *elements_generated = ( (long)current_element - (long)first_element ) /
- sizeof *first_element ;
- /*** return success message ***/
- return note_time_table_filled ;
- }
-
-
-
- NOTE_TIME_TABLE_ELEMENT *get_element(NOTE_TIME_TABLE_ELEMENT *first_element,
- unsigned long number ,
- TIME time)
- {
- NOTE_TIME_TABLE_ELEMENT *current_element, *previous_element ;
- unsigned long low = 0, mid, high = number ;
- int found = FALSE ;
-
- /*** Has already the first element a higher time ? ***/
- if (first_element->time >= time) return first_element ;
-
- /*** Has the last element a lower time ? ***/
- current_element = first_element + number - 1 ;
- if (current_element->time < time) return NULL ; /* failed */
-
- /*** Now, number shurely is greater or equal 2 ! ***/
- while (!found)
- {
- mid = (low + high) / 2 ;
- current_element = first_element + mid ;
- previous_element = current_element - 1 ;
- if ((current_element->time >= time) && (previous_element->time >= time))
- high = mid ;
- else if (current_element->time < time) low = mid ;
- else found = TRUE ;
- if (!high) { current_element = first_element ; found = TRUE ; } ;
- }
- return current_element ;
- }
-